package pers.ree.demo.concurrent.lock;

/**
 * 验证使用String作为同步锁的demo
 * 1.直接使用String常量当锁
 * 2.使用new String()当锁
 */
public class StringLockDemo {

    // 危险！其他类如果也使用"123"作为锁，会出现阻塞，如：StringLock2.lock2
    private static final String lock1 = "123";
    // 可以保证同一个类中使用lock11作为锁的同步性，又不会导致其他类被意外的阻塞，如：使用StringLock2.lock22的代码不会被使用lock11的代码阻塞
    private static final String lock11 = new String("123");


    public static void testLock1() {
        synchronized (lock1) {
            System.out.println("StringLockDemo testLock1 in " + Thread.currentThread().getName() + " begin");
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("StringLockDemo testLock1 in " + Thread.currentThread().getName() + " end");
        }
    }

    public static void testLock11() {
        synchronized (lock11) {
            System.out.println("StringLockDemo testLock11 in " + Thread.currentThread().getName() + " begin");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("StringLockDemo testLock11 in " + Thread.currentThread().getName() + " end");
        }
    }

    public static void exeCase1() {
        System.out.println("StringLockDemo exeCase1 begin");

        new Thread(new Runnable() {
            @Override
            public void run() {
                StringLockDemo.testLock1();
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                StringLock2.testLock2();
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("StringLockDemo exeCase1 in " + Thread.currentThread().getName() + " begin");

                synchronized ("123") { // 效果与使用StringLock2.lock2一样
                    System.out.println("StringLockDemo exeCase1 in " + Thread.currentThread().getName() + " end");
                }
            }
        }).start();

        System.out.println("StringLockDemo exeCase1 end");
    }

    public static void exeCase2() {
        System.out.println("StringLockDemo exeCase2 begin");

        new Thread(new Runnable() {
            @Override
            public void run() {
                StringLockDemo.testLock11();
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                StringLock2.testLock22();
            }
        }).start();

        System.out.println("StringLockDemo exeCase2 end");
    }

    public static void main(String[] args) {
        exeCase1();

        exeCase2();
    }
}

class StringLock2 {

    private static final String lock2 = "123";
    private static final String lock22 = new String("123");


    public static void testLock2() {
        synchronized (lock2) {
            System.out.println("StringLock2 testLock2 in " + Thread.currentThread().getName());
        }
    }

    public static void testLock22() {
        synchronized (lock22) {
            System.out.println("StringLock2 testLock22 in " + Thread.currentThread().getName());
        }
    }
}
